/* function : startGame
 * usage    : startGame(player_num, stage);
 * --------------------
 * to start a new game
 *///{{{

var startGame = function (_player_num, _stage) {
    player_num = _player_num;
    var local_stage = window.localStorage["stage"];


    var url_stage = window.location.href.split("#")[1];
    if (_stage < 0){
        stage = -_stage;
    }else if (url_stage !== undefined && parseInt(url_stage).toString() !== "NaN"){
        stage = parseInt(url_stage);
    }else if (local_stage !== undefined){
        stage = parseInt(local_stage);
    }else{
        stage = _stage;
    }

    player_cnt = key_cnt = door_cnt = skill_cnt = 0;
    initGraphics();
//    var map = maps[playerNum][stage];
//    var map = map_json;
    $.getJSON("./maps/map"+stage+".js", function (map) {
 
        //{{{
        var tot = 0;
        for (var z=0; z<map.length; ++z){
            for (var x=0; x<map[z].length; ++x){
                for (var y=0; y<map[z][x].length; ++y){
                    if (map[z][x][y][0] == 0){
                        continue;
                    }
                    ++tot;
                }
            }
        }
        $("#processbar")[0].max = tot;
        $("#processbar")[0].value = 0;
        /*
        $("#processbar")[0].onchange = function () {
            if (this.max <= this.value){
                for (var i in robots){
                    send_msg(i, "^.^ Game started.");
                }

            }
        };
        */

        for (var z=0; z<map.length; ++z){
            for (var x=0; x<map[z].length; ++x){
                for (var y=0; y<map[z][x].length; ++y){
                    var t = map[z][x][y][0];
                    var s = map[z][x][y][1];
                    if (t==0){
                        continue;
                    }
                    if (t == ObjType.ROBOT){
                        if (player_cnt >= player_num) continue;
                        loadCollada(t, MODEL_FILES[t][s], x, y, z);
                        rob_ori_pos.push(new THREE.Vector3(x,y,z));
                        rob_ori_rot.push(new THREE.Vector3(0,0,0));
                        ++player_cnt;
                    }else if (t == ObjType.DOOR){
                        loadCollada(t, MODEL_FILES[t][s], x, y, z);
                        doors[door_cnt].subType = s;
                        ++door_cnt;
                    }else if (t == ObjType.KEY){
                        loadCollada(t, MODEL_FILES[t][s], x, y, z);
                        keys[key_cnt].subType = s;
                        ++key_cnt;
                    }else if (t == ObjType.SKILL){
                        loadCollada(t, MODEL_FILES[t][s], x, y, z);
                        skills[skill_cnt].subType = s;
                        ++skill_cnt;
                    }else{
                        loadCollada(t, MODEL_FILES[t], x, y, z);
                    }
                }
            }
        }
       
        //}}}
        //setInterval("draw(robot)", 0.1);
        //draw(robot);
        animate();
    });
}
//}}}
    

var forAllBGM = function (callback) {
    callback($("#bgm0")[0]);
    callback($("#bgm1")[0]);
    callback($("#bgm2")[0]);
};

var playBGM = function () {
    forAllBGM(function (bgm) {
        bgm.pause();
        bgm.currentTime = 0;
    });
    var tmp = $("#bgm" + Math.floor(Math.random()*3))[0];
    tmp.play();
    console.log(tmp.duration);
    setTimeout(playBGM, (tmp.duration) * 1000);
};

var playAudioEffect = function (str) {
    forAllBGM(function (bgm) {
        bgm.volume = 0.5;
    });
    var tmp = $("#" + str)[0];
    tmp.pause();
    tmp.currentTime = 0;
    tmp.play();
    setTimeout(function () {
        forAllBGM(function (bgm) {
            bgm.volume = 1;
        });
    }, $("#" + str)[0].duration);
}

/* function : rotate
 * usage    : _vector3 = rotate(vector3, degree);
 * --------------------
 * rotate a vector
 * {{{
 */
var rotate = function (vec3, deg) {
    var cos = Math.cos(deg);
    var sin = Math.sin(deg);
    return new THREE.Vector3(
            vec3.x*cos - vec3.y*sin,
            vec3.x*sin + vec3.y*cos,
            vec3.z);
}
//}}}

var robotMeet = function (obj) {
    for (var i=0; i<robots.length; ++i){
        if (robots[i].meet(obj)){
            return i;
        }
    }
    return -1;
}

var ballMeet = function (obj) {
    var balls = objs[ObjType.BALL];
    for (var i=0; i<balls.length; ++i){
        if (obj.isPointIn(balls[i].dae.position)){
            return i;
        }
    }
    return -1;
}

var dieRobot = function (idx) {
    var robot = robots[idx];
    robot.dae.position.copy(rob_ori_pos[idx]);
    robot.dae.rotation.copy(rob_ori_rot[idx]);
    robot.rot.set(0,0,0);
    robot.pos.set(0,0,0);
    robot.jumping = 0;
    robot.jumped = 0;
    cam_rel_vecs[idx] = ((new THREE.Vector3(0,0,-0.1)).addSelf(ROBOT_FORE).setLength(10).negate());
    robot.keys = [];
    for (var j=0; j<4; ++j){
        $(".status_bar.p"+(idx+1)+".key"+j).removeClass("gain");
    };
    playAudioEffect("meow");
};

var send_msg = function (robot_id, msg) {
    $(".status_bar.msg."+("p"+(robot_id+1))).each(function () {
        if ($(this).hasClass("locked")){
            var idx = parseInt($(this).attr("id"));
            clearTimeout(idx);
            $(this).removeClass("locked");
        }
        $(this).addClass("locked");
        $(this)[0].innerText = msg;
        var dom = $(this);
        $(this).attr("id", ""+setTimeout(function () {
            console.log(dom);
            dom.removeClass("locked");
            dom[0].innerText = "I must find the kitty!";
        }, 2000));
    });
};

var check = function () {
    if (dae_loaded < dae_cnt) return;
    var i, j;
    
    //ball
    for (i=0; i<balls.length; ++i){
        var ball = balls[i];
        var disapper =(!(inRange(ball.dae.position.x, -100, 100)
                         && inRange(ball.dae.position.y, -100, 100)
                         && inRange(ball.dae.position.z, -100, 100)
                        ));
        //robot
        for (j=0; j<robots.length; ++j){
            var robot = robots[j];
            if (robot.isPointIn(ball.dae.position)){
                dieRobot(j);
                send_msg(j, "T.T I hate the ball!");
                disapper = true;
            }
        }
        //stone
        for (j=0; j<stones.length; ++j){
            var stone = stones[j];
            if (stone.isPointIn(ball.dae.position)){
                disapper = true;
            }
        }
        //monster
        for (j=0; j<monsters.length; ++j){
            var monster = monsters[j];
            if (monster.isPointIn(ball.dae.position)){
                scene.remove(monster.dae);
                monsters.splice(j, 1);
                --j;
                disapper = true;
            }
        }
        //door
        for (j=0; j<doors.length; ++j){
            var door = doors[j];
            if (door.isPointIn(ball.dae.position)){
                disapper = true;
            }
        }
        if (disapper){
            scene.remove(ball.dae);
            balls.splice(i, 1);
            --i;
        }
    }
    var winners = [];
    
    //robot
    for (i=0; i<robots.length; ++i){
        var robot = robots[i];
        var replace = (robot.dae.position.z <= -5);
        var backplace = false;
        
        //send_msg(i, "-.- I must find the kitty!");
        //kitty
        for (j=0; j<kittys.length; ++j){
            var kitty = kittys[j];
            if (kitty.meet(robot) || robot.meet(kitty)){
                winners += i;
                send_msg(i, "CHEERS! I have found Kitty #" + (j+1));
                console.log("kitty meets robot");
            }
        }
        //stone
        for (j=0; j<stones.length; ++j){
            var stone = stones[j];
            if (stone.meet(robot) || robot.meet(stone)){
                send_msg(i, "HURT! I knocked on a stone!");
                backplace = true;
            }
        }
        //monster
        for (j=0; j<monsters.length; ++j){
            var monster = monsters[j];
            if (monster.meet(robot) || robot.meet(monster)){
                send_msg(i, "T.T  I hate that monster!");
                replace = true;
            }
        }
        //door
        for (j=0; j<doors.length; ++j){
            var door = doors[j];
            if ((!robot.hasKey(door.subType))
                && (door.meet(robot) || robot.meet(door))){
                send_msg(i, ":( I dont have the key....");
                backplace = true;
            }
        }
        //key
        for (j=0; j<keys.length; ++j){
            var key = keys[j];
            if (key.meet(robot) || robot.meet(key)){
                robot.gainKey(key.subType);
                send_msg(i, ":) I got a key!");
                $(".status_bar.p"+(i+1)+".key"+key.subType).addClass("gain");
                playAudioEffect("unlock");
            }
        }
        //skill
        for (j=0; j<skills.length; ++j){
            var skill = skills[j];
            var gaining = false;
            if (skill.meet(robot) || robot.meet(skill)){
                switch (skill.subType){
                    case SkillType.JUMP:
                        if (robot.max_jump >= 1) break;
                        robot.max_jump = 1;
                        gaining = true;
                        break;
                    case SkillType.SHOOT:
                        if (robot.can_shoot === 1) break;
                        robot.can_shoot = 1;
                        gaining = true;
                        break;
                    case SkillType.DBL_JUMP:
                        if (robot.max_jump === 2) break;
                        robot.max_jump = 2;
                        gaining = true;
                        break;
                    case SkillType.SPEED_UP:
                        if (robot.speed >= 2) break;
                        robot.speed = 2;
                        gaining = true;
                        break;
                    default:
                        break;
                }
                if (gaining === false) continue;
                $(".status_bar.p"+(i+1)+".skill"+skill.subType).addClass("gain");
                send_msg(i, "^.^ I learned a new skill!");
                playAudioEffect("eat");
            }
        }
        //deal place
        if (replace){
            dieRobot(i);
        }else if (backplace){
            robot.dae.position.copy(robot.last_position);
            robot.jumping = 0;
            robot.jumped = 0;
        }
    }

    //robot&robot
    relist = [];
    for (i=0; i<robots.length; ++i){
        if (i in relist) continue;
        robot = robots[i];
        for (j=i+1; j<robots.length; ++j){
            if (robots[j].meet(robot) || robot.meet(robots[j])){
                relist.push(i);
                relist.push(j);
                break;
            }
        }
    }
    for (i in relist){
        console.log("two robots meet");
        send_msg(relist[i], "Wow! You meet another robot!");
        robot = robots[relist[i]];
        robot.dae.position.copy(robot.last_position);
        robot.jumping = 0;
        robot.jumped = 0;
    }
    //deal with win-scene
    if (winners.length){
        for (i=0; i<robots.length; ++i){
            robots[i].pos.set(0,0,0);
            robots[i].speed = 0;
        }
        ++stage;
        window.localStorage["stage"] = stage;
        if (stage === 11){
            alert("You have found all kittys!, Congritulations!\n"
                    + "You can add '#[num]' to the url to choose stage.\n"
                    + "e.g. http://www.xxx.com/index.html#3");
        }else if (confirm("Robot Finds the Kitty! Next stage?")){
            console.log(stage);
            startGame(player_num, -stage);
        }else{
            alert("You can click "
                    + ((player_num === 1) ? "[single]" : "[double]")
                    + " to continue");
        }
    }
}

var addGravity = function () {
    for (i=0; i<robots.length; ++i){
        robots[i].dae.position.z -= G;
    }
    for (i=0; i<stones.length; ++i){
        while ((robot = robotMeet(stones[i])) > -1){
            robots[robot].dae.position.z += G;
            robots[robot].jumped = 0;
            robots[robot].jumping = 0;
        }
    }
    for (var i=0; i<doors.length; ++i){
        for (var j=0; j<robots.length; ++j){
            if (robots[j].meet(doors[i]) && !robots[j].hasKey(doors[i].subType)){
                robots[j].dae.position.z += G;
                robots[j].jumped = 0;
                robots[j].jumping = 0;
            }
        }
    }
    for (i=0; i<robots.length; ++i){
        for (var j=0; j<robots.length; ++j){
            if (i === j) continue;
            if (!robots[i].meet(robots[j])) continue;
            if (robots[j].dae.position.z > robots[i].dae.position.z){
                robots[j].dae.position.z += G;
	    		robots[j].jumped = 0;
	    		robots[j].jumping = 0;
            }else{
                robots[i].dae.position.z += G;
	    		robots[i].jumped = 0;
	    		robots[i].jumping = 0;
            }
        }
    }

}

